//definitions
#define rx 2
#define tx 3
#define dataSize 4
#define readTimeOut 500000 //define how long the readBus function has to run in microseconds

//global variables
byte dataIn[dataSize];
byte dataOut[dataSize];
byte tempByte;
boolean dataFound;
boolean dataToWrite;
unsigned long readStart;
int incomingByte = dataIn[1];
int powerA1 = 11;
int powerA2 = 10;
int powerB1 = 9;
int powerB2 = 8;
int currentSensor1 = 0;
int currentSensor2 = 1;
int voltageSensorA = 2;
int voltageSensorB = 3;
int val = 0;



//setup
void setup(){
  
  Serial.begin(19200);
  
  pinMode(rx, OUTPUT);
  pinMode(tx, OUTPUT);
  //both HIGH to transmit
  
  dataFound = false;
  dataToWrite = false;
  
  digitalWrite(rx, LOW);
  digitalWrite(tx, LOW);
}


void loop(){
  
  //I seperated the bus routine into read and write, they could be one method, but modularity=flexability
  readBus(dataIn);
  if(dataFound){
      //someone said something to you
      //carry on accordingly      
  }
  
  
  //if you have something to say, simply fill it into the 'dataOut' array and set dataToWrite=true
  if(dataToWrite){
      writeBus(dataOut);
  }
  if(incomingByte >= B11110000){
    if(incomingByte%2 == 1){
      digitalWrite(powerA1, HIGH);
    }
    else{
      digitalWrite(powerA1, LOW);
    }
    if(incomingByte%4 >= 2){
      digitalWrite(powerA2, HIGH);
    }
    else{
      digitalWrite(powerA2, LOW);
    }
    if(incomingByte%8 >= 4){
      digitalWrite(powerB1, HIGH);
    }
    else{
      digitalWrite(powerB1, LOW);
    }
    if(incomingByte%16 >= 8){
      digitalWrite(powerB2, HIGH);
    }
    else{
      digitalWrite(powerB2, LOW);
    }
  }
  if(incomingByte < B11110000){
    if(incomingByte == 0){
      val = analogRead(currentSensor1);
      dataOut[0] = 0;
      dataOut[1] = incomingByte;
      dataOut[2] = val>>8;
      dataOut[3] = val && B11111111;
    }
    if(incomingByte == 1){
      val = analogRead(currentSensor2);
      dataOut[0] = 0;
      dataOut[1] = incomingByte;
      dataOut[2] = val>>8;
      dataOut[3] = val && B11111111;
    }
    if(incomingByte == 2){
      val = analogRead(voltageSensorA);
      dataOut[0] = 0;
      dataOut[1] = incomingByte;
      dataOut[2] = val>>8;
      dataOut[3] = val && B11111111;
    }
    if(incomingByte == 3){
      val = analogRead(voltageSensorB);
      dataOut[0] = 0;
      dataOut[1] = incomingByte;
      dataOut[2] = val>>8;
      dataOut[3] = val && B11111111;
  }
  
}
}
   


void writeBus(byte *dataOut){
  
  digitalWrite(rx, HIGH);
  digitalWrite(tx, HIGH);
  delayMicroseconds(1);  
  
  for(int i=0; i<dataSize; i++){
    Serial.write(dataOut[i]);   
  }
  
  dataToWrite = false; 
  
  //stop writing
  digitalWrite(rx, LOW);
  digitalWrite(tx, LOW);
  delayMicroseconds(1);
     
}


void readBus(byte *dataIn){
 readStart = micros();
 dataFound = false;
 while(Serial.available()>0 && (micros()-readStart)<readTimeOut){              //while there are bytes available in the serial buffer (128 max)...
     tempByte = Serial.read();  //read them into 'tempByte'...
     if(addressCheck(tempByte) && (micros()-readStart)<readTimeOut){           //if tempByte is an address you are looking for...
           
           while(Serial.available()<3 && (micros()-readStart)<readTimeOut){    //wait for the other bytes in the message to arrive or the whole group of 4 bytes will be lost
            delayMicroseconds(1);                                              //they will probably be there anyway   
           }
         
           dataFound = true;
           dataIn[0] = tempByte;
             for(int i=1; i<dataSize; i++){
                dataIn[i] = Serial.read();       
             }
      }
  }
   
}



boolean addressCheck(byte x){
//fill in this switch statement with whatever addresses you want to pay attention to  
  switch (x){
   case B11111101:         // normally an address you pay attention to would go here
        return true;
   default:
        return false;
  }
    
}
